// // Copyright 2015-2017 Parity Technologies (UK) Ltd.
// // This file is part of Parity.

// // Parity is free software: you can redistribute it and/or modify
// // it under the terms of the GNU General Public License as published by
// // the Free Software Foundation, either version 3 of the License, or
// // (at your option) any later version.

// // Parity is distributed in the hope that it will be useful,
// // but WITHOUT ANY WARRANTY; without even the implied warranty of
// // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// // GNU General Public License for more details.

// // You should have received a copy of the GNU General Public License
// // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
// use ring;
// // enum Mode { Aes128Gcm, Aes256Gcm }

// struct OneNonceSequence(Option<ring::aead::Nonce>);

// impl OneNonceSequence {
//     /// Constructs the sequence allowing `advance()` to be called
//     /// `allowed_invocations` times.
//     fn new(nonce: ring::aead::Nonce) -> Self {
//         Self(Some(nonce))
//     }
// }

// impl ring::aead::NonceSequence for OneNonceSequence {
//     fn advance(&mut self) -> Result<ring::aead::Nonce, ring::error::Unspecified> {
//         self.0.take().ok_or(ring::error::Unspecified)
//     }
// }

// fn make_key<K: ring::aead::BoundKey<OneNonceSequence>>(
//     algorithm: &'static ring::aead::Algorithm,
//     key: &[u8; 16],
//     nonce: ring::aead::Nonce,
// ) -> K {
//     let key = ring::aead::UnboundKey::new(algorithm, key).unwrap();
//     let nonce_sequence = OneNonceSequence::new(nonce);
//     K::new(key, nonce_sequence)
// }

// /// AES GCM encryptor.
// pub struct Encryptor<'a> {
//     s_key: ring::aead::SealingKey<OneNonceSequence>,
//     aad: &'a [u8],
// }

// impl<'a> Encryptor<'a> {
//     // key = fixed 16 length ,nonce = fixed 12 length
//     // if length of key is more than 16,then contract to 16 length
//     // if length of nonce is more than 12,then contract to 12 length
//     pub fn aes_128_gcm(m_key: &[u8], nonce: &[u8]) -> Result<Encryptor<'a>, anyhow::Error> {
//         let mut aes_key = [0u8; 16];
//         let size = m_key.len();
//         if size > 16 {
//             aes_key.copy_from_slice(&m_key[..16]);
//         } else {
//             let mut p_m_key = m_key.iter().take(size).collect::<Vec<&u8>>();
//             let mut p_m_key_vec = vec![];
//             p_m_key.extend_from_slice(aes_key.iter().take(16 - size).collect::<Vec<_>>().as_ref());
//             for x in &p_m_key {
//                 p_m_key_vec.push(**x);
//             }
//             aes_key.copy_from_slice(&p_m_key_vec[..16]);
//         }
//         let mut aes_nonce = [0u8; ring::aead::NONCE_LEN];

//         let size = nonce.len();
//         if size > ring::aead::NONCE_LEN {
//             aes_nonce.copy_from_slice(&nonce[..ring::aead::NONCE_LEN]);
//         } else {
//             let mut p_m_nonce = nonce.iter().take(size).collect::<Vec<&u8>>();
//             let mut p_m_nonce_vec = vec![];
//             p_m_nonce.extend_from_slice(
//                 aes_nonce
//                     .iter()
//                     .take(ring::aead::NONCE_LEN - size)
//                     .collect::<Vec<_>>()
//                     .as_ref(),
//             );
//             for x in &p_m_nonce {
//                 p_m_nonce_vec.push(**x);
//             }
//             aes_nonce.copy_from_slice(&p_m_nonce_vec[..ring::aead::NONCE_LEN]);
//         }

//         let key_nonce = ring::aead::Nonce::assume_unique_for_key(aes_nonce);

//         let key: ring::aead::SealingKey<OneNonceSequence> =
//             make_key(&ring::aead::AES_128_GCM, &aes_key, key_nonce);

//         Ok(Encryptor {
//             s_key: key,
//             aad: &[],
//         })
//     }

//     /// Please note that the pair (key, nonce) must never be reused. Using random nonces
//     /// limits the number of messages encrypted with the same key to 2^32 (cf. [[1]])
//     ///
//     /// [1]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
//     pub fn encrypt(&mut self, mut data: Vec<u8>) -> Result<Vec<u8>, anyhow::Error> {
//         // let tag_len =  ring::aead::AES_128_GCM.tag_len();
//         // data.extend(::std::iter::repeat(0).take(tag_len));
//         match self
//             .s_key
//             .seal_in_place_append_tag(ring::aead::Aad::from(self.aad), &mut data)
//         {
//             Ok(()) => Ok(data),
//             Err(e) => {
//                 log::error!("seal_in_place_append_tag e={}", e.to_string());
//                 anyhow::bail!("seal_in_place_append_tag error")
//             }
//         }
//     }
// }

// /// AES GCM decryptor.
// pub struct Decryptor<'a> {
//     o_key: ring::aead::OpeningKey<OneNonceSequence>,
//     aad: &'a [u8],
// }

// impl<'a> Decryptor<'a> {
//     // key = fixed 16 length ,nonce = fixed 12 length
//     // if length of key is more than 16,then contract to 16 length
//     // if length of nonce is more than 12,then contract to 12 length
//     pub fn aes_128_gcm(m_key: &[u8], nonce: &[u8]) -> Result<Decryptor<'a>, anyhow::Error> {
//         let mut aes_key = [0u8; 16];
//         let size = m_key.len();
//         if size > 16 {
//             aes_key.copy_from_slice(&m_key[..16]);
//         } else {
//             let mut p_m_key = m_key.iter().take(size).collect::<Vec<&u8>>();
//             let mut p_m_key_vec = vec![];
//             p_m_key.extend_from_slice(aes_key.iter().take(16 - size).collect::<Vec<_>>().as_ref());
//             for x in &p_m_key {
//                 p_m_key_vec.push(**x);
//             }
//             aes_key.copy_from_slice(&p_m_key_vec[..16]);
//         }
//         let mut aes_nonce = [0u8; ring::aead::NONCE_LEN];

//         let size = nonce.len();
//         if size > ring::aead::NONCE_LEN {
//             aes_nonce.copy_from_slice(&nonce[..ring::aead::NONCE_LEN]);
//         } else {
//             let mut p_m_nonce = nonce.iter().take(size).collect::<Vec<&u8>>();
//             let mut p_m_nonce_vec = vec![];
//             p_m_nonce.extend_from_slice(
//                 aes_nonce
//                     .iter()
//                     .take(ring::aead::NONCE_LEN - size)
//                     .collect::<Vec<_>>()
//                     .as_ref(),
//             );
//             for x in &p_m_nonce {
//                 p_m_nonce_vec.push(**x);
//             }
//             aes_nonce.copy_from_slice(&p_m_nonce_vec[..ring::aead::NONCE_LEN]);
//         }

//         let key_nonce = ring::aead::Nonce::assume_unique_for_key(aes_nonce);

//         let key: ring::aead::OpeningKey<OneNonceSequence> =
//             make_key(&ring::aead::AES_128_GCM, &aes_key, key_nonce);
//         Ok(Decryptor {
//             o_key: key,
//             aad: &[],
//         })
//     }

//     pub fn decrypt(&mut self, mut data: Vec<u8>) -> Result<Vec<u8>, anyhow::Error> {
//         match self
//             .o_key
//             .open_in_place(ring::aead::Aad::from(self.aad), &mut data)
//         {
//             Ok(in_out_result) => {
//                 let mut vec = Vec::new();
//                 vec.extend_from_slice(in_out_result);
//                 Ok(vec)
//             }
//             Err(e) => {
//                 log::error!("open_in_place e={}", e.to_string());
//                 anyhow::bail!("open_in_place error")
//             }
//         }
//     }
// }

// pub fn aes_128_encrypt(app_secret: &[u8], nonce: &[u8], to_encrypt: String) -> Option<String> {
//     let encrypt_opt = Encryptor::aes_128_gcm(app_secret, nonce);
//     if let Ok(mut encryptor) = encrypt_opt {
//         let some_encrypt_text = encryptor.encrypt(to_encrypt.as_bytes().to_vec());
//         if let Ok(encrypt_text) = some_encrypt_text {
//             return Some(hex::encode(encrypt_text));
//         }
//     }

//     None
// }

// pub fn aes_128_decrypt(app_secret: &[u8], nonce: &[u8], to_decrypt: String) -> Option<String> {
//     if let Ok(hex_byte) = hex::decode(to_decrypt.as_bytes()) {
//         if let Ok(mut decryptor) = Decryptor::aes_128_gcm(app_secret, nonce) {
//             if let Ok(decrypt_text) = decryptor.decrypt(hex_byte) {
//                 return String::from_utf8(decrypt_text).ok();
//             };
//         };
//     }

//     None
// }

// #[cfg(test)]
// mod tests {
//     use super::{aes_128_decrypt, aes_128_encrypt, Decryptor, Encryptor};
//     #[test]
//     fn test_ring_aes_gcm_128() {
//         use crate::utils::logutil;
//         use crate::utils::random_byte;

//         logutil::global_log_init("coolink","DEBUG");

//         let secret = b"1234567890123456";
//         let nonce = b"123456789012";
//         // let secret = b"123";
//         // let nonce = b"456";

//         // let secret = b"123456789012345678";
//         // let nonce = b"12345678901212";
//         let message = b"So many books, so little time";

//         let ciphertext = Encryptor::aes_128_gcm(secret, nonce)
//             .unwrap()
//             .encrypt(message.to_vec())
//             .unwrap();

//         log::info!("Encrypt ciphertext = {:02x?} ", ciphertext);
//         assert!(ciphertext != message);

//         let plaintext = Decryptor::aes_128_gcm(secret, nonce)
//             .unwrap()
//             .decrypt(ciphertext)
//             .unwrap();

//         log::info!(
//             "Decryptor plaintext = {:?}",
//             String::from_utf8(plaintext.clone()).unwrap()
//         );

//         assert_eq!(plaintext, message);

//         let e1 = aes_128_encrypt(
//             "123456".to_owned().as_bytes(),
//             "123456".to_owned().as_bytes(),
//             "hello,world!".to_owned(),
//         );
//         assert_eq!(e1.is_none(), false);
//         log::info!("e1 unwrap  = {:?}", e1.clone().unwrap());

//         let e2 = aes_128_decrypt(
//             "123456".to_owned().as_bytes(),
//             "123456".to_owned().as_bytes(),
//             e1.clone().unwrap_or("".to_owned()),
//         );
//         assert_eq!(e2.is_none(), false);
//         assert_eq!("hello,world!", e2.unwrap());

//         let (app_secret, nonce) = random_byte::gen_app_secret_and_nonce("".to_owned());
//         let secret_bytes = hex::decode(&app_secret).unwrap();
//         let nonce_bytes = hex::decode(&nonce).unwrap();
//         let some_unique_srv_id = aes_128_encrypt(
//             &secret_bytes,
//             &nonce_bytes,
//             "group_addr_struct.unique_server_id".to_owned(),
//         );
//         log::info!(
//             "some_unique_srv_id aes_128_encrypt  = {:?}",
//             some_unique_srv_id
//         );
//         let dencrypt = aes_128_decrypt(&secret_bytes, &nonce_bytes, some_unique_srv_id.unwrap());
//         assert_eq!("group_addr_struct.unique_server_id", dencrypt.unwrap());
//     }
// }
